#pragma once
#include <iostream>
#include <string>
#include <sys/epoll.h>
#include "Log.hpp"
static const int ignore = 128; // 这个值直接忽略，大于0即可
using namespace ns_log;
class Multiplex
{
public:
    virtual bool AddEvents(int fd, uint32_t events) = 0;
    virtual int Wait(struct epoll_event *revents, int maxnum, int timeout) = 0;
    virtual bool ModEvents(int fd, uint32_t events)  = 0;
};

class Epoller : public Multiplex
{
private:
    bool _ModEvents(int fd, uint32_t events,int oper) 
    {
        struct epoll_event ev;
        ev.data.fd = fd;
        ev.events = events;
        int n = ::epoll_ctl(_epollfd, oper, fd, &ev);
        if (n < 0)
        {
            LOG(ERROR, "epoll ctl a fd = %d failed,events = %s\n", fd, SetEpollEventStr(events).c_str());
            return false;
        }
        LOG(INFO, "epoll_ctl success,event = %s\n", SetEpollEventStr(events).c_str());
        return true;
    }
public:
    Epoller()
    {
        _epollfd = ::epoll_create(ignore);
        if (_epollfd < 0)
        {
            LOG(FATAL, "epoll create error!\n");
        }
    }
    std::string SetEpollEventStr(uint32_t events)
    {
        std::string res;
        if (events & EPOLLIN)
            res += "EPOLLIN";
        if (events & EPOLLOUT)
            res += "|EPOLLOUT";
        if (events & EPOLLET)
            res += "|EPOLLET";
        return res;
    }
    bool AddEvents(int fd, uint32_t events) override
    {
       return _ModEvents(fd,events,EPOLL_CTL_ADD);
    }
    bool ModEvents(int fd, uint32_t events) override
    {
        return _ModEvents(fd,events,EPOLL_CTL_MOD);
    }
    int Wait(struct epoll_event *revents, int maxnum, int timeout)
    {
        return ::epoll_wait(_epollfd, revents, maxnum, timeout);
    }
    ~Epoller()
    {
    }

private:
    int _epollfd;
};